 /***GameManager By GYLite 2022-12-26
 * 游戏管理器，管理游戏的适配、初始化，启动，结束，资源加载等功能
*/
class GameManager {
	private static _instance: GameManager;
	public static version: string = window["game_version"] ? window["game_version"] : "";
	public static game: Main;
	public static WIN_WIDTH: number = 1440;
	public static WIN_HEIGHT: number = 810;
	public static debug: boolean = !window["release"];
	public static getInstance(): GameManager {
		if (GameManager._instance == null)new GameManager;
		return GameManager._instance;
	}
	
	public debugWidth: number = 1920;
	public debugHeight: number = 1080;
	public gameScale: number = 1;
	public maxRatio:number;
	public minRatio:number;
	public startTime: number;
	public endTime: number;
	public deviceVer: string;
	public firstIn:boolean=true;	
	/**预留100个id位*/public uidCount: number = 100;
	private _isGameStart: boolean;
	private _configMgr: ConfigManager;
	private _stageWidth:number;
	private _stageHeight:number;
	private _urlSize:boolean;	
	private _urlDict: any;
	/**录屏状态0没开始 1开始录制 2录制结束 3录制成功 4录制失败*/
	public recordState:number = 0;
	public errorTexture:egret.Texture;	
	public static inited:boolean;
	public isReload:boolean=false;
	public isMathEnter:boolean = false;	
	public globalLoad:{globalLoadPercent:Function,setPercent:Function,addLoadingUI:Function,removeLoadingUI:Function,hasLoading:boolean};
	
	public constructor() {
		let s = this;
		GameManager._instance = s;		
		//设备版本
		s.deviceVer = egret.WebGLUtils.checkCanUseWebGL() ? "" : "";
		s._urlDict = {};
		s.maxRatio = s.minRatio = NaN;
		let platForm:string = UserData.getInstance().getPlatform();
		s.maxRatio = NaN;
		s.minRatio = 4/3;
		s.globalLoad = window["globalLoad"]?window["globalLoad"]:{
			hasLoading:true,
			globalLoadPercent:function(cur,max,label){},
			setPercent:function(cur,max,label){},
			addLoadingUI:function():void{},
			removeLoadingUI:function():void{},
		};
	}
	public setConfig(val: any): void {
		let s = this;
		if (s._configMgr == null)
			s._configMgr = new ConfigManager(val);		
		// s._config = val;
		let w: number = +UserData.getInstance().getQueryVariable("designWidth");
		let h: number = +UserData.getInstance().getQueryVariable("designHeight");
		if (w > 0 && h > 0) {
			s._urlSize = true;
			s.stardardWidth = w;
			s.stardardHeight = h;
		}
		else {
			s.resetStardardSize();
		}

	}
	public get configMgr(): ConfigManager {
		return this._configMgr;
	}
	public get config(): any {
		return this._configMgr.config;
	}
	/**获取配置的公共库版本号
	 * @param uiPath 模块名称
	*/
	public getLibDirVer(uiPath: string): string {
		let s = this;
		return s._configMgr.getLibDirVer(uiPath);
	}

	/**获取配置的模块版本号
	 * @param uiPath 模块名称
	*/
	public getMdDirVer(uiPath: string): string {
		let s = this;
		return s._configMgr.getMdDirVer(uiPath);
	}
	//预加载列表
	public get preloads(): string[] {
		return this._configMgr.config.preloads;
	}
	/**引擎初始化完成，未进入游戏，游戏配置、资源未加载*/
	public engineInited():void
	{let s = this;
		GYLite.GYLoader.defCompressSound = MySound;				
	}
	/**游戏初始化完成,进入游戏，游戏配置、资源已加载*/
	public gameInit(): void {
		var s = this;
		GameManager.inited = true;		
		s.errorTexture = Main.instance.getRes("error.png");
		UIControl.getInstance().init();		
		
		Dispatcher.getInstance().addEventListener(Dispatcher.GAME_READY, s.gameReady, s);				
		if(egret.wxgame.wx)
		{
			egret.wxgame.wx.onShow(s.viewIn.bind(s));
			egret.wxgame.wx.onHide(s.viewOut.bind(s));
		}
		else
		{
			document.addEventListener("visibilitychange", function () {
				if (document.visibilityState == "visible") {
					s.viewIn();
				}
				if (document.visibilityState == "hidden") {
					s.viewOut();
				}
	
			});
		}		
	}

	/**改变帧率
	 * @param frameRate 20-60内
	 * */
	public changeFrameRate(frameRate:number=60):void
	{
		Log.writeLog("帧率改变！" + frameRate,Log.WARN);
		GYLite.GYSprite.stage.frameRate = frameRate;
		Main.setStorage("wdCode_noEngoughPower", frameRate+"");
	}	
	public showView:boolean = true;
	private frontBackChange(d: any): void {		
		if (d == null) return;
		let s = this;
		if (d.data) {
			if (d.data.type == 1) {
				s.viewOut();
				s.showView = false
			}
			else if (d.data.type == 2) {
				s.viewIn();
				s.showView = true
			}
		}
	}
	private viewIn(): void {
		let s = this;
		Log.writeLog(MultiLang.str64, Log.WARN);
		let ctx = egret["web"].WebAudioDecode.ctx;
		if(ctx && ctx.state != "running")
		{
			ProtoExt.resumeAudioContext();
		}		
		SoundManager.instance.resume();
		egret.ticker.resume();
		s.showView = false;
	}
	private viewOut(): void {
		let s= this;
		Log.writeLog(MultiLang.str63, Log.WARN);		
		SoundManager.instance.pause();
		egret.ticker.pause();
		s.showView = true;
	}
	public debugStart(): void {
		var s = this;
	}	
	public gameStart(): void {
		var s = this;
		let userData:UserData;
		userData = UserData.getInstance();
		s._isGameStart = true;
		let modulePath: string = userData.getQueryModuleName();		
		
		Log.writeLog(MultiLang.str55 + (modulePath ? modulePath : ""), Log.INFO);
		if (s.isNoEnterModule()) {			
			Log.writeLog(MultiLang.str72,Log.WARN);
		}
		else {
			modulePath = (modulePath == null ? (window["gy_module"] ? window["gy_module"] : "exercise") : modulePath);
			if (modulePath == "wait") {
				return;
			}
			if (userData.getQueryVariable("state") == 2)//预加载
			{
				GameManager.getInstance().globalLoad.removeLoadingUI();
				UIControl.getInstance().preloadUI(modulePath);
			}
			else {
				let fileId:string = userData.getQueryVariable("fileId");
				UIControl.getInstance().openUI(modulePath, null, Math.random() + "", { mask: true },true);				
				
			}
		}
	}
	/**启动游戏的垃圾回收*/
	public gc():void
	{		
		let t = Date.now();
		GYLite.GYSprite.gc();//引擎垃圾回收		
		LayerManager.getInstance().gc();//清除全局的尺寸适配
		SoundManager.gc();//声音进行垃圾回收		
		Log.writeLog("gc耗时:"+(Date.now() - t));
	}	
	/**交互场景就绪*/
	private gameReady(e:egret.Event):void
	{	
	}
	public gameEnd(): void {
		var s = this;
		// s.dispatchEvent(new GYViewEvent(GYViewEvent.UPDATE_COMPLETE));
	}
	/**屏幕宽高比类型
	 * @return 1 偏方型 2 偏横版 3 长方形
	*/
	public getRatioType():number
	{let s = this;
		let stRatio:number=(9/16 + 3/4)/2;
		let ratio:number = s._stageHeight / s._stageWidth;
		if(ratio != ratio)
			ratio = s._gameHeight / s._gameWidth;
		if(ratio < 9/16)return 3;
		return stRatio < ratio?1:2;
	}

	public checkEnterFromMath()
	{
		let s = this;
		return s.isMathEnter;
	}


	public resize(w: number, h: number): void {
		var s = this;
		// console.log("a",s.stardardWidth / w);
		let sclX: number, sclY: number,scl:number;
		let ww:number,wh:number;
		ww = window.screen?window.screen.width:0;
		wh = window.screen?window.screen.height:0;
		Log.writeLog("尺寸变更:w-" + w + ",h-" + h + "," + "winW:" + egret.Capabilities.boundingClientWidth + "-" + "winH:" + egret.Capabilities.boundingClientHeight + "," + ww + "-" + wh + ",devicePixelRatio:" + window.devicePixelRatio, Log.WARN);
		if(ww > 0 && w == 0)
		{			
			let temp:number;
			if(ww < wh)
			{
				temp = ww;
				ww = wh;
				wh = temp;
			}
			w = ww;
			h = wh;
		}
		s._gameWidth = s._stageWidth = w;
		s._gameHeight = s._stageHeight = h;	
		scl = w / h;
		if(scl > s.maxRatio)		
			s._stageWidth = h * s.maxRatio;		
		else if(scl < s.minRatio)		
			s._stageHeight = w / s.minRatio;
		s.resetStardardSize();
		sclX = s._stageWidth / s.stardardWidth;
		sclY = s._stageHeight / s.stardardHeight;		
		if (sclX < sclY)
			s.gameScale = sclX;
		else
			s.gameScale = sclY;		
		LayerManager.getInstance().resize(s._stageWidth, s._stageHeight, w - s._stageWidth >> 1, h - s._stageHeight >> 1);
	}
	private resetStardardSize():void
	{let s = this;		
		if(s._configMgr.config.autoSize && !s._urlSize)
		{			
			if(s.getRatioType() == 1)
			{
				s.stardardWidth = 1440;
				s.stardardHeight = 1080;
			}
			else
			{
				s.stardardWidth = 1920;
				s.stardardHeight = 1080;
			}
		}
		else
		{
			if(!s._urlSize)
			{
				s.stardardWidth = s._configMgr.config.designWidth;
				s.stardardHeight = s._configMgr.config.designHeight;
			}			
		}		
	}
	public get gameHeight(): number {
		var s = this;
		return s._gameHeight;
	}

	public get gameWidth(): number {
		var s = this;
		return s._gameWidth;
	}
	/**实际使用的舞台高度*/
	public get stageHeight(): number {
		var s = this;
		return s._stageHeight;
	}
	/**实际使用的舞台宽度*/
	public get stageWidth(): number {
		var s = this;
		return s._stageWidth;
	}
	/**是否不存在模块进入*/
	public isNoEnterModule(): boolean {
		return window["gy_module"] == null && UserData.getInstance().getQueryModuleName() == null;
	}	
	private netCall(d:any):void
	{
		let s = this;
		if (d && d.data) {
			Net.getInstance().state = d.data.state;	
			if(Net.getInstance().state  == Net.CONNECTED)
			{				
				Log.writeLog("断网重连重新请求数据 netCall" , Log.IMPORTANT);
			}	
		}
	}
	/**全局加载数据
	 * @param path 文件路径
	 * @param callBackFunc 回调
	 * @param thisObject
	 * @param progFunc 进度回调
	 * @param type 类型
	 * @param method 请求类型
	 * @param getCache 是否检测缓存
	 * @param loadInfoParam 附件参数	 
	 * @param failReloadCount 失败后重新尝试的次数
	*/
	public loadData(path: string, callBackFunc: Function, thisObject: any, progFunc = null, type = 6, method = "get", param = null, loadInfoParam: any = null,failReloadCount:number=0): GYLite.LoadInfo {
		let s = this;		
		let obj:any = { path: path, callBackFunc: callBackFunc, thisObject: thisObject, progFunc: progFunc, type: type, method: method, param: param, loadInfoParam: loadInfoParam, failReloadCount:failReloadCount};
		
		
		let loadInfo: GYLite.LoadInfo;
		loadInfo = Main.instance.myLoader.loadData(path, s.dataLoadComp, s, s.dataLoadProg, type, method, {object:obj,loadCount:0});
		if (loadInfoParam) {
			for (var key in loadInfoParam) {
				loadInfo[key] = loadInfoParam[key];
			}
		}
		return null;
	}
	private dataLoadProg(e:egret.Event):void
	{
		let s = this;
		let obj:any = e.target.loadInfo.param.object;
		if(obj.progFunc!=null)
		{			
			obj.progFunc.call(obj.thisObject, e);
		}
	}
	private dataLoadComp(l:GYLite.LoadInfo):void
	{let s = this;
		let obj:any = l.param.object;
		let loadInfo:GYLite.LoadInfo;
		if(l.content == null)
		{			
			++l.param.loadCount;
			if(l.param.loadCount >= obj.failReloadCount)
			{
				l.param.loadCount = 0;	
				Log.writeLog(MultiLang.str62 + ",dataLoadComp:" + obj.path + "!" + l.msg,Log.WARN);
				return;
			}							
			GYLite.TimeManager.timeOut(function():void{		
				let url:string;
				url=obj.path.indexOf("?") > -1?(obj.path + "&reload=" + Date.now()):(obj.path + "?reload=" + Date.now());
				loadInfo = Main.instance.myLoader.loadData(url, s.dataLoadComp, s, s.dataLoadProg, obj.type, obj.method, {object:obj,loadCount:l.param.loadCount});
				if (obj.loadInfoParam) {
					for (var key in obj.loadInfoParam) {
						loadInfo[key] = obj.loadInfoParam[key];
					}
				}
			},s,2000);				
            Log.writeLog("dataLoadComp:" + MultiLang.str68 + "-" + obj.path + "-" + l.msg,Log.WARN);
			return;
		}		
		if(obj.callBackFunc!=null)
		{
			l.param = obj.param;
			obj.callBackFunc.call(obj.thisObject, l);
		}
	}
	public reload(delay: number = -1): void {
		let s = this;
		if (delay == -1) {
			location.reload();
			return;
		}
		GYLite.TimeManager.timeOut(function (): void {
			location.reload();
		}, s, delay);
	}
	public destroy():void{
			let s = this;
			if(s._destroyed)return;
			s._destroyed = true;
			// UIControl.getInstance().disposeAllUI();
			// GYLite.GYLoader.dispose();
			// GYLite.GYSprite.dispose();
			egret.ticker.pause();
	}

	public get destroyed():boolean
	{
		return this._destroyed;
	}
	private _destroyed:boolean = false;
	/**标准宽度*/public stardardWidth: number;
	/**标准高度*/public stardardHeight: number;
	/**当前设备宽度*/private _gameWidth: number;
	/**当前设备高度*/private _gameHeight: number;
}